package com.usooft.metaTalent.core.system.service.base;

import com.usooft.framework.core.query.Limit;
import com.usooft.framework.core.query.Page;
import com.usooft.metaTalent.core.system.entity.Employee;
import com.usooft.metaTalent.core.system.mapper.EmployeeMapper;
import com.usooft.metaTalent.core.system.query.EmployeeQuery;
import com.usooft.metaTalent.core.system.service.EmployeeService;
import com.usooft.metaTalent.core.system.wrapper.EmployeeWrapper;
import java.lang.Boolean;
import java.lang.Long;
import java.lang.Override;
import java.lang.String;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

public abstract class BaseEmployeeService implements EmployeeService {
    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public Employee get(@NonNull Long id) {
        return find(id).orElseThrow();
    }

    @Override
    public Optional<Employee> find(@NonNull Long id) {
        return Optional.ofNullable(employeeMapper.get(id));
    }

    @Override
    public List<EmployeeWrapper> list(EmployeeQuery query) {
        return employeeMapper.list(query);
    }

    @Override
    public Page<EmployeeWrapper> page(EmployeeQuery query) {
        int rows = employeeMapper.count(query.getFilter());
        return new Page<>(rows, rows == 0 ? new ArrayList<>() : employeeMapper.list(query));
    }

    protected Optional<Employee> findOne(EmployeeQuery.Filter filter, EmployeeQuery.Sorts sorts) {
        List<EmployeeWrapper> wrappers = list(EmployeeQuery.builder()
                                .filter(filter)
                                .sorts(sorts)
                                .limit(Limit.rowCount(1))
                                .build());
        return wrappers.stream().findFirst().map(Function.identity());
    }

    protected Optional<Employee> findOne(EmployeeQuery.Filter filter) {
        return findOne(filter, EmployeeQuery.Sorts.builder().build());
    }

    @Override
    public int count(EmployeeQuery.Filter filter) {
        return employeeMapper.count(filter);
    }

    protected Employee internalAdd(String phoneNumber, String password, String name, String gender,
            Boolean admin, Boolean locked) {
        Employee employee = new Employee();
        employee.setPhoneNumber(phoneNumber);
        employee.setPassword(password);
        employee.setName(name);
        employee.setGender(gender);
        employee.setAdmin(admin);
        employee.setLocked(locked);

        employee.setCreatedDate(LocalDateTime.now());
        employee.setVersion(0);
        employee.setLoginStatus(false);
        employeeMapper.add(employee);
        return employee;
    }

    protected void internalUpdate(@NonNull Employee employee) {
        employee.setLastModifiedDate(LocalDateTime.now());

        int rows = employeeMapper.update(employee);
        if (rows == 0) {
            throw new OptimisticLockingFailureException("更新失败。可能员工 (" + employee.getId() + ") 的版本 (" + employee.getVersion() + ") 已不是最新");
        }
        employee.setVersion(employee.getVersion() + 1);
    }

    protected void internalDelete(@NonNull Employee employee) {
        int rows = employeeMapper.delete(employee);
        if (rows == 0) {
            throw new OptimisticLockingFailureException("删除失败。可能员工 (" + employee.getId() + ") 的版本 (" + employee.getVersion() + ") 已不是最新");
        }
    }

    @Override
    public Optional<? extends Employee> findByPhoneNumber(@NonNull String phoneNumber) {
        Assert.notNull(phoneNumber, "必须提供手机号");
        return findOne(EmployeeQuery.Filter.builder()
                .phoneNumberIs(phoneNumber)
                .build());
    }
}
